package com.smart.service.impl;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.thread.ExecutorBuilder;
import cn.xuyanwu.spring.file.storage.FileInfo;
import cn.xuyanwu.spring.file.storage.FileStorageService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smart.common.PageInfo;
import com.smart.common.enums.OpenStatusEnum;
import com.smart.common.utils.AssertUtil;
import com.smart.context.SessionContext;
import com.smart.mapper.ProjectMapper;
import com.smart.mapper.ProjectUseControlMapper;
import com.smart.mapper.StreetMapper;
import com.smart.mapper.UserIdentificationMapper;
import com.smart.model.customdo.UseControlCustomDO;
import com.smart.model.domain.ProjectDO;
import com.smart.model.domain.ProjectEquDO;
import com.smart.model.domain.ProjectUseControlDO;
import com.smart.model.domain.StreetDO;
import com.smart.model.domain.UserIdentificationDO;
import com.smart.model.dtomapper.UserIdentificationDtoMapper;
import com.smart.model.request.UserIdentificationEquBindRequest;
import com.smart.model.request.UserIdentificationPageRequest;
import com.smart.model.request.UserIdentificationRequest;
import com.smart.model.vo.ProjectUseControlVO;
import com.smart.model.vo.UserIdentificationPageVO;
import com.smart.model.vo.UserIdentificationVO;
import com.smart.service.ProjectEquService;
import com.smart.service.ProjectUseControlService;
import com.smart.service.UserIdentificationService;
import com.smart.utils.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.stream.Collectors;

/**
 * @author zhanghong
 */
@Slf4j
@Service
public class UserIdentificationServiceImpl extends ServiceImpl<UserIdentificationMapper, UserIdentificationDO> implements UserIdentificationService {
    @Autowired
    private UserIdentificationMapper userIdentificationMapper;
    @Autowired
    private ProjectMapper projectMapper;
    @Autowired
    private ProjectEquService projectEquService;
    @Autowired
    private StreetMapper streetMapper;
    @Autowired
    private ProjectUseControlService projectUseControlService;
    @Autowired
    private ProjectUseControlMapper projectUseControlMapper;
    @Autowired
    private FileStorageService fileStorageService;

    @Override
    public UserIdentificationVO getByEquNo(String equNo) {
        UserIdentificationDO userIdentificationDO = userIdentificationMapper.queryByEquNo(equNo);
        UserIdentificationVO userIdentificationVO = UserIdentificationDtoMapper.INSTANCE.do2VO(userIdentificationDO);
        return userIdentificationVO;
    }
    @Override
    public JSONObject record(UserIdentificationRequest request) {
        AssertUtil.assertNotNull(request.getEquNo(), "设备编号不能为空");
        AssertUtil.assertNotNull(request.getIdCard(), "身份证号不能为空");

        //同一个设备同一个人只保留一条信息(避免重复识别造成多条数据情况)
        lambdaUpdate().eq(UserIdentificationDO::getEquNo, request.getEquNo()).eq(UserIdentificationDO::getIdCard, request.getIdCard()).remove();

        MultipartFile faceImgFile = FileUtil.base64ToMultipartFile(request.getFaceImg());
        FileInfo faceImgInfo = fileStorageService.of(faceImgFile).upload();

        MultipartFile idCardImgFile = FileUtil.base64ToMultipartFile(request.getIdCardImg());
        FileInfo idCardImgInfo = fileStorageService.of(idCardImgFile).upload();

        UserIdentificationDO userIdentificationDO = UserIdentificationDtoMapper.INSTANCE.request2DO(request);
        userIdentificationDO.setFaceImg(faceImgInfo.getUrl());
        userIdentificationDO.setIdCardImg(idCardImgInfo.getUrl());
        save(userIdentificationDO);

        log.info("识别的信息 userIdentificationDO={}", JSON.toJSONString(userIdentificationDO));
        JSONObject result = new JSONObject();
        result.put("success", "1");
        return result;
    }

    @Override
    public PageInfo<UserIdentificationPageVO> pageQuery(UserIdentificationPageRequest request) {
        List<ProjectDO> projects = userIdentificationMapper.listIdentificationQuery(request);
        if (StringUtils.isNotBlank(request.getManageOpenStatus())) {
            projects = projects.stream().filter(item-> Objects.equals(item.getManageOpenStatus(), request.getManageOpenStatus())).collect(Collectors.toList());
        }
        long count = projects.size();
        List<ProjectDO> page = ListUtil.page(request.getPageNum() - 1, request.getPageSize(), projects);
        List<UserIdentificationPageVO> result = page.stream().map(this::fillInfo).collect(Collectors.toList());
        return PageInfo.build(request.getPageNum(), request.getPageSize(), result, count);
    }

    @Override
    public UserIdentificationPageVO getEquMangeInfoByProjectId(Long projectId) {
        AssertUtil.assertNotNull(projectId, "项目id不能为空");
        ProjectDO project = projectMapper.selectDOById(projectId);
        AssertUtil.assertNotNull(project, "项目不存在");
        return fillInfo(project);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveEquInfo(UserIdentificationEquBindRequest request) {
        AssertUtil.assertNotNull(request.getProjectId(), "项目id不能为空");
        ProjectDO project = projectMapper.selectDOById(request.getProjectId());
        AssertUtil.assertNotNull(project, "项目不存在");

        //删除重写
        projectEquService.lambdaUpdate().eq(ProjectEquDO::getProjectId, request.getProjectId()).remove();
        for (String equNo : request.getEquNoList()) {
            ProjectEquDO equDO = new ProjectEquDO();
            equDO.setProjectId(request.getProjectId());
            equDO.setEqu(equNo);
            projectEquService.save(equDO);
        }
        return true;
    }

    @Override
    public Boolean clearEquNo(String equNo) {
        this.lambdaUpdate().eq(UserIdentificationDO::getEquNo, equNo).remove();
        return true;
    }

    @Override
    public ProjectUseControlVO getOpenInfo() {
        Long projectId = SessionContext.getProjectId();
        AssertUtil.assertNotNull(projectId, "云服务平台登录方可使用");
        UseControlCustomDO projectDO = projectUseControlMapper.queryByProjectId2(projectId);
        AssertUtil.assertNotNull(projectDO, "项目数据不存在");
        return assembleProjectInfo(projectDO);
    }

    private UserIdentificationPageVO fillInfo(ProjectDO project) {
        UserIdentificationPageVO userIdentificationVO = new UserIdentificationPageVO();

        //项目使用控制, 默认未开通
        userIdentificationVO.setManageOpenStatus(OpenStatusEnum.UN_OPEN.name());
        List<ProjectUseControlDO> projectUseControlList = projectUseControlService.lambdaQuery().eq(ProjectUseControlDO::getProjectId, project.getId()).list();
        if (CollectionUtils.isNotEmpty(projectUseControlList)) {
            ProjectUseControlDO control = projectUseControlList.get(0);
            userIdentificationVO.setManageOpenStatus(control.getManageOpenStatus());
            userIdentificationVO.setManageOpenExpire(control.getManageOpenExpire());
        }

        userIdentificationVO.setProjectId(project.getId());
        userIdentificationVO.setProjectName(project.getProjectName());
        userIdentificationVO.setProjectNumber(project.getProjectNumber());
        userIdentificationVO.setEngineeringType(project.getEngineeringType());
        userIdentificationVO.setConstructionStatus(project.getConstructionStatus());
        userIdentificationVO.setStreetCode(project.getStreetCode());

        // 街道信息
        StreetDO streetDO = streetMapper.selectDOByCode(project.getStreetCode());
        userIdentificationVO.setStreetName(Optional.ofNullable(streetDO).map(StreetDO::getName).orElse(null));

        // 查询设备列表
        List<ProjectEquDO> list = projectEquService.lambdaQuery().eq(ProjectEquDO::getProjectId, project.getId()).list();
        userIdentificationVO.setEquNoList(list.stream().map(ProjectEquDO::getEqu).collect(Collectors.toList()));
        return userIdentificationVO;
    }

    private ProjectUseControlVO assembleProjectInfo(UseControlCustomDO project) {
        if (project == null) {
            return null;
        }
        ProjectUseControlVO projectUseControlVO = new ProjectUseControlVO();
        projectUseControlVO.setProjectId(project.getProjectId());
        projectUseControlVO.setProjectName(project.getProjectName());
        projectUseControlVO.setProjectNumber(project.getProjectNumber());
        projectUseControlVO.setConstructionStatus(project.getConstructionStatus());
        projectUseControlVO.setStreetCode(project.getStreetCode());
        projectUseControlVO.setAddress(project.getAddress());
        projectUseControlVO.setEngineeringType(project.getEngineeringType());
        projectUseControlVO.setQualityRegistrationNumber(project.getQualityRegistrationNumber());
        StreetDO streetDO = streetMapper.selectDOByCode(project.getStreetCode());
        if (streetDO != null) {
            projectUseControlVO.setStreetName(streetDO.getName());
        }

        projectUseControlVO.setId(project.getId());
        projectUseControlVO.setManageOpenStatus(Optional.ofNullable(project.getManageOpenStatus()).orElse(OpenStatusEnum.UN_OPEN.name()));
        projectUseControlVO.setManageOpenExpire(Optional.ofNullable(project.getManageOpenExpire()).orElse(null));
        projectUseControlVO.setReportOpenStatus(Optional.ofNullable(project.getReportOpenStatus()).orElse(OpenStatusEnum.UN_OPEN.name()));
        projectUseControlVO.setReportOpenExpire(Optional.ofNullable(project.getReportOpenExpire()).orElse(null));
        projectUseControlVO.setHotWorkOpenStatus(Optional.ofNullable(project.getHotWorkOpenStatus()).orElse(OpenStatusEnum.UN_OPEN.name()));
        projectUseControlVO.setHotWorkOpenExpire(Optional.ofNullable(project.getHotWorkOpenExpire()).orElse(null));
        projectUseControlVO.setHotWorkMax(Optional.ofNullable(project.getHotWorkMax()).orElse(null));
        projectUseControlVO.setHotWorkAvailableNum(Optional.ofNullable(project.getHotWorkAvailableNum()).orElse(null));

        // 查询设备列表
        List<ProjectEquDO> list = projectEquService.lambdaQuery().eq(ProjectEquDO::getProjectId, project.getProjectId()).list();
        if (CollectionUtils.isNotEmpty(list)) {
            projectUseControlVO.setEquList(list.stream().map(ProjectEquDO::getEqu).collect(Collectors.toList()));
        }
        return projectUseControlVO;
    }
}
